package com.yumeng.example.test.service.impl;


import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.baomidou.mybatisplus.extension.toolkit.SqlHelper;
import com.yumeng.common.api.PageData;
import com.yumeng.common.exception.DemoException;
import com.yumeng.common.helper.AssertHelper;
import com.yumeng.common.utils.RandomUtils;
import com.yumeng.example.test.dao.TestDao;
import com.yumeng.example.test.dao.mapper.TestMapper;
import com.yumeng.example.test.dto.page.TestPageDto;
import com.yumeng.example.test.entity.Test;
import com.yumeng.example.test.service.ExampleTestService;
import com.yumeng.framework.core.base.service.impl.BaseServiceImpl;
import lombok.extern.slf4j.Slf4j;
import org.apache.ibatis.session.SqlSession;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * @author wxd
 * @date 2021/8/27 23:07
 */
@Slf4j
@Service
public class ExampleTestServiceImpl extends BaseServiceImpl<Test> implements ExampleTestService {

    private final TestDao testDao;

    @Autowired
    public ExampleTestServiceImpl(TestDao testDao) {
        this.testDao = testDao;
    }

    @Override
    public void doTest() {
        log.info("此处执行Demo模块下，doTest()方法");
    }

    @Override
    public boolean testExecute(Integer type) {
/*        if (type == 1){
            return insertBatchSomeColumn();
        }else if (type == 2){
            return DbHelper.retBoolWeak(testDao.mapper().deleteAll());
        }*/
        return testDao.deleteRetBool(null);
    }

    @Override
    public Object testQuery(Integer type) {
        return testDao.testQuery();
/*        if (type == 1){
            return testFirstLevelCache();
        }else if (type == 2){
            return testSecondLevelCache();
        }else{
            throw new DemoException("type 值异常");
        }*/
    }


    /**
     * 不进行 count sql 优化，解决 MP 无法自动优化 SQL 问题，这时候你需要自己查询 count 部分
     * page.setOptimizeCountSql(false);
     * 当 total 为小于 0 或者设置 setSearchCount(false) 分页插件不会进行 count 查询
     * 要点!! 分页返回的对象与传入的对象是同一个
     * @param pageDto
     * @return
     */
    @Override
    public PageData<Test> getTestPageList(TestPageDto pageDto, int type) {
        return testDao.selectTestPage(pageDto, type);
    }





    //=========================================================================================================================

    //测试乐观锁
    private boolean testOptimisticLocker(){
        //Test test = testDao.mapper().selectById(1);
        //test.setStrVal(RandomUtils.randomString(10));

        Test test = new Test();
        test.setTestId(1L);
        test.setStrVal(RandomUtils.randomString(10));
        test.setVersion(0);

        boolean b = testDao.updateByIdRetBool(test);
        return b;
    }







    /**
     * 测试MP一级缓存
     * 1、分别使用testMapper、testMapper2调用 （不命中缓存）
     * 2、使用testMapper调用2次，但两次调用之间清除缓存（不命中缓存）
     * 3、使用testMapper调用2次（命中缓存）
     */
    private Object testFirstLevelCache(){
        SqlSession sqlSession = null;
        SqlSession sqlSession2 = null;
        try{
            Class<?> entityClass = testDao.getEntityClass();
            sqlSession = SqlHelper.sqlSession(entityClass);
            sqlSession2 = SqlHelper.sqlSession(entityClass);
            TestMapper testMapper = sqlSession.getMapper(TestMapper.class);
            TestMapper testMapper2 = sqlSession2.getMapper(TestMapper.class);
            testMapper.selectById(1L);
            //sqlSession.clearCache();
            return testMapper.selectById(1L);//testMapper2
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            if (sqlSession != null) {
                sqlSession.close();
                sqlSession2.close();
            }
        }
        return null;
    }

    /**
     * 测试MP二级缓存
     */
    private Object testSecondLevelCache(){
        SqlSession sqlSession1 = null;
        Class<?> entityClass = testDao.getEntityClass();
        try{
            sqlSession1 = SqlHelper.sqlSession(entityClass);
            TestMapper testMapper = sqlSession1.getMapper(TestMapper.class);
            Test testObj = testMapper.selectById(1);
            testObj.setStrVal("abc测试");
            Test testObj2 = testMapper.selectById(1);
            //由于一级缓存的存在，testObj与testObj2是同一个对象
            log.info("sqlSession :: testObj2 :: strVal={}", testObj2.getStrVal());
            AssertHelper.assertEquals(testObj, testObj2);
        }catch (Exception e){
            e.printStackTrace();
        } finally {
            if (sqlSession1 != null) {
                sqlSession1.close();
            }
        }
        SqlSession sqlSession2 = null;
        try{
            sqlSession2 = SqlHelper.sqlSession(entityClass);
            TestMapper testMapper2 = sqlSession2.getMapper(TestMapper.class);
            Test testObj3 = testMapper2.selectById(1);
            Test testObj4 = testMapper2.selectById(1);
            //当二级缓存未启用时，testObj3与testObj4是同一个对象
            //当二级缓存启用时，sqlSession1.close()时，会把对象缓存到二级缓存中，student2 和 student3 都是反序列化得到的， 为不同的实例
            log.info("sqlSession2 :: testObj3 :: strVal={}", testObj3.getStrVal());
            log.info("sqlSession2 :: testObj4 :: strVal={}", testObj4.getStrVal());
            testObj3.setStrVal("112233你好");
            log.info("sqlSession2 :: testObj3 :: strVal={}", testObj3.getStrVal());
            log.info("sqlSession2 :: testObj4 :: strVal={}", testObj4.getStrVal());
            AssertHelper.assertNotEquals(testObj3, testObj4);
        }catch (Exception e){
            e.printStackTrace();
        } finally {
            if (sqlSession2 != null) {
                sqlSession2.close();
            }
        }
        return null;
    }



    @Override
    public Test getOneTest(Long testId) {
        Test test = testDao.mapper().selectById(testId);
        return test;
    }

    @Override
    public boolean insertBatch() {
/*        List<Test> list = getInitData(6);
        return testDao.mapper(list);*/
        throw new DemoException("待实现");
    }

    @Override
    public boolean updateBatchIds() {
/*        List<Test> list = getInitData(3);
        list.get(0).setTestId(1L);
        list.get(1).setTestId(2L);
        list.get(2).setTestId(3L);
        testDao.updateBatchIds(list);
        return true;*/

        throw new DemoException("待实现");
    }

    @Override
    public boolean logicDeleteById(Long id) {
        return testDao.logicDeleteByIdRetBool(id);
    }

    @Override
    public boolean logicDeleteBatchIds(List<Long> ids) {
        //return testDao.logicDeleteBatchIdsRetBool(ids);
        throw new DemoException("待实现");
    }

    @Override
    public boolean logicDelete() {
/*        UpdateWrapper wrapper = new UpdateWrapper();
        wrapper.eq("int_val", 2);
        DynamicTableHelper.setIdParam(getTableName(), 1L);
        return testDao.logicDeleteRetBool(wrapper);*/
        throw new DemoException("待实现");
    }

    @Override
    public boolean logicDeleteByMap() {
        Map<String, Object> columnMap = new HashMap<>();
        columnMap.put("str_val", "aa");
        columnMap.put("dou_val", "1.2");
        return testDao.logicDeleteByMapRetBool(columnMap);
    }

    @Override
    public boolean testVersion(Integer type) {
        if (type.equals(1)){
            Test test = new Test();
            test.setVersion(0);
            test.setIntVal(22);

            UpdateWrapper wrapper = new UpdateWrapper();
            wrapper.eq("str_val", "bb");
            boolean b = testDao.updateRetBool(test, wrapper);
            return b;
        }else if (type.equals(2)){
            Test test = new Test();
            test.setTestId(1L);
            //test.setVersion(0);
            test.setDouVal(1.22);
            return testDao.updateByIdRetBool(test);
        }else if (type.equals(3)){
            List<Test> list = new ArrayList<>();
            Test test = new Test();
            test.setTestId(1L);
            test.setVersion(0);
            test.setDouVal(1.22);
            test.setStrVal("aa");
            list.add(test);

            test = new Test();
            test.setTestId(2L);
            test.setVersion(0);
            test.setDouVal(1.33);
            test.setStrVal("bb");
            list.add(test);

            test = new Test();
            test.setTestId(3L);
            test.setVersion(0);
            test.setDouVal(1.44);
            test.setStrVal("cc");
            list.add(test);

            test = new Test();
            test.setTestId(4L);
            test.setVersion(0);
            test.setDouVal(1.55);
            test.setStrVal("dd");
            list.add(test);
            testDao.mapper().updateById(list);
            //testDao.mapper().updateById(list);
            return true;
        }else{
            throw new DemoException("type值无效");
        }
    }


    //==============================================================

    private boolean insertBatchSomeColumn(){
        List<Test> list = getInitData(10);
        return testDao.insertBatchRetBool(list);

        //return saveBatch(list);
    }



    private List<Test> getInitData(int size){
        List<Test> list = new ArrayList<>(size);
        for (int i = 0; i < size; i++){
            list.add(new Test(true));
        }
        return list;
    }
}
